package com.ruoyi.service.impl;

import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.entity.JrPermission;
import com.ruoyi.entity.vo.PermissionBatchDTO;
import com.ruoyi.mapper.PermissionMapper;
import com.ruoyi.service.PermissionService;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class PermissionServiceImpl implements PermissionService {
    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Override
    public void savePermissions(PermissionBatchDTO dto) {
        // 参数校验
        if ((dto.getUserIds() == null || dto.getUserIds().isEmpty())
                && (dto.getRoleIds() == null || dto.getRoleIds().isEmpty())) {
            throw new IllegalArgumentException("必须指定用户或角色");
        }

        // 1. 查询用户/角色在该资源类型下的所有旧资源ID
        List<Long> oldRefIds = permissionMapper.selectOldRefIds(
                dto.getUserIds(),
                dto.getRoleIds(),
                dto.getRefType()
        );

        // 记录旧 refIds 以便后续使用
        log.info("旧权限涉及的资源ID: {}", oldRefIds);

        // 2. 如果存在旧资源ID，执行批量删除
        if (!oldRefIds.isEmpty()) {
            int deleteCount = permissionMapper.deleteByConditions(
                    dto.getUserIds(),
                    dto.getRoleIds(),
                    oldRefIds, // 使用查询到的旧资源ID
                    dto.getRefType()
            );
            log.info("已删除 {} 条旧权限记录", deleteCount);
        }

        // 打印详细日志
        log.info("精确删除条件: refType={}, refIds={}, userIds={}, roleIds={}",
                dto.getRefType(), oldRefIds, dto.getUserIds(),
                dto.getRoleIds());

        // 3. 插入新权限（保持原有逻辑）
        List<JrPermission> permissions = new ArrayList<>();
        for (Long refId : dto.getRefIds()) {
            for (Long userId : dto.getUserIds()) {
                permissions.add(buildPermission(dto, refId, userId, null));
            }
            for (Long roleId : dto.getRoleIds()) {
                permissions.add(buildPermission(dto, refId, null, roleId));
            }
        }

            // 批量插入新权限
            if (!permissions.isEmpty()) {
                permissionMapper.batchInsert(permissions);
                log.info("插入新权限 {} 条",  permissions.size());
            }
    }

    @Override
    public Map<String, Object> getPermissionsConfig(PermissionBatchDTO dto) {
        List<JrPermission> permissions = permissionMapper.selectPermissions(dto);

        Map<String, Object> result = new HashMap<>();
        // 获取文件/文件夹ID列表
        List<Long> refIds = permissions.stream()
                .map(JrPermission::getRefId)
                .distinct()
                .collect(Collectors.toList());

        // 获取权限配置（取第一条记录的权限设置）
        if (!permissions.isEmpty()) {
            JrPermission first = permissions.get(0);
            result.put("canDelete", first.getCanDelete());
            result.put("canView", first.getCanView());
            result.put("canEdit", first.getCanEdit());
            result.put("canAdd", first.getCanAdd());
        }

        result.put("refIds", refIds);
        return result;
    }


    @Override
    public boolean checkPermission(Integer refType, Long refId, String action) {
        SysUser user = SecurityUtils.getLoginUser().getUser();

        // 管理员直接放行
        if (user.isAdmin()) {
            return true;
        }

        // 获取用户角色列表
        List<Long> roleIds = userRoleMapper.selectRoleIdsByUserId(user.getUserId());

        // 查询权限记录
        List<JrPermission> permissions = permissionMapper.selectByUserAndResource(
                user.getUserId(),
                roleIds,
                refType,
                refId
        );
        // 无权限记录 → 直接拒绝
        if (permissions.isEmpty()) {
            return false;
        }

        // 检查所有记录的当前操作权限：必须全部为 false 才拒绝
        boolean hasPermission = permissions.stream()
                .anyMatch(p -> hasPermission(p, action)); // 只要有一条允许即放行

        log.info("权限校验结果: {}", hasPermission);

        // 打印调试日志
        log.info("Checking permission: refType={}, refId={}, action={}", refType, refId, action);
        // 检查操作权限
        return permissions.stream().anyMatch(p -> hasPermission(p, action));
    }

    private boolean hasPermission(JrPermission permission, String action) {
        switch (action.toLowerCase()) {
            case "can_delete": return Boolean.TRUE.equals(permission.getCanDelete());
            case "can_edit": return Boolean.TRUE.equals(permission.getCanEdit());
            case "can_view": return Boolean.TRUE.equals(permission.getCanView());
            case "can_add": return Boolean.TRUE.equals(permission.getCanAdd());
            default: return false;
        }
    }

    private JrPermission buildPermission(PermissionBatchDTO dto, Long refId, Long userId, Long roleId) {
        JrPermission permission = new JrPermission();
        permission.setRefType(dto.getRefType());
        permission.setRefId(refId);
        permission.setUserId(userId);
        permission.setRoleId(roleId);
        permission.setCanDelete(dto.getCanDelete());
        permission.setCanView(dto.getCanView());
        permission.setCanEdit(dto.getCanEdit());
        permission.setCanAdd(dto.getCanAdd());
        return permission;
    }
}
